home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Games / WormWars / Source / fe.c < prev    next >
C/C++ Source or Header  |  2002-03-12  |  36KB  |  980 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <exec/alerts.h>
  4.  
  5. #include "diff.h"
  6. #include "same.h"
  7. #include "amiga.h"
  8.  
  9. #include <intuition/intuition.h> // for struct Window, etc.
  10. #include <libraries/gadtools.h>  // for GT_VisualInfo, etc.
  11.  
  12. #include <stdlib.h>              // for EXIT_SUCCESS, etc.
  13.  
  14. MODULE UWORD chip CustomPointer[] =
  15. {   0x0000, 0x0000, /* reserved */
  16.  
  17.     0xF000, 0xF800, /* 1st row 1st plane, 1st row 2nd plane */
  18.     0xF000, 0x8800, /* 2nd row 1st plane, 2nd row 2nd plane */
  19.     0xF000, 0x8800, /* 3rd row 1st plane, 3rd row 2nd plane */
  20.     0xF000, 0x8800, /* 4th row 1st plane, 4th row 2nd plane */
  21.     0xF000, 0x8800, /* 5th row 1st plane, 5th row 2nd plane */
  22.     0x8000, 0xF800, /* 6th row 1st plane, 6th row 2nd plane */
  23.  
  24.     0x0000, 0x0000  /* reserved */
  25. };
  26.  
  27. #define ALTJUMP         5
  28. #define UNDERLINEOFFSET (58 + STARTYPIXEL)
  29.  
  30. /* pseudo-gadgets */
  31. #define GADGETX         (-3) // negatives must be within brackets
  32. #define EMPTYGADGET    ((FIELDY / 2) -  9)
  33. #define SILVERGADGET   ((FIELDY / 2) -  6)
  34. #define GOLDGADGET     ((FIELDY / 2) -  3)
  35. #define DYNAMITEGADGET  (FIELDY / 2)
  36. #define WOODGADGET     ((FIELDY / 2) +  3)
  37. #define STONEGADGET    ((FIELDY / 2) +  6)
  38. #define METALGADGET    ((FIELDY / 2) +  9)
  39.  
  40. MODULE void setpointer(UBYTE brush);
  41. MODULE void dot(void);
  42. MODULE void undot(void);
  43. MODULE void stamp(UBYTE square);
  44. MODULE void fillfield(UBYTE which);
  45. MODULE void underline(UBYTE square);
  46. MODULE SBYTE xpixeltosquare(SWORD x);
  47. MODULE SBYTE ypixeltosquare(SWORD y);
  48. MODULE void levelappend(void);
  49. MODULE void leveldelete(void);
  50. MODULE void levelerase(void);
  51. MODULE void levelinsert(void);
  52. MODULE void copyfield(UBYTE source, UBYTE destination);
  53.  
  54. IMPORT struct Window*        MainWindowPtr;
  55. IMPORT struct Menu*          MenuPtr;
  56. IMPORT struct VisualInfo*    VisualInfoPtr;
  57. IMPORT struct timerequest*   TimerRqPtr;
  58. IMPORT struct InputEvent     GameEvent;
  59. IMPORT struct Screen*        ScreenPtr;
  60.  
  61. IMPORT struct TeleportStruct teleport[MAXLEVELS + 1][4];
  62.  
  63. IMPORT ABOOL               clearthem,
  64.                            icons,
  65.                            modified;
  66. IMPORT SBYTE               a,
  67.                            board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
  68.                            startx[MAXLEVELS + 1],
  69.                            starty[MAXLEVELS + 1],
  70.                            fex = FIELDX / 2,
  71.                            fey = FIELDY / 2,
  72.                            level, levels;
  73.  
  74. MODULE ABOOL               sticky = FALSE;
  75. MODULE UBYTE               brush  = STONE;
  76.  
  77. AGLOBAL void fieldedit(void)
  78. {   AUTO    ABOOL                leftdown  = FALSE,
  79.                                  timer     = FALSE;
  80.     AUTO    SBYTE                mergelevels,
  81.                                  pointerx, pointery,
  82.                                  which,
  83.                                  x, y;
  84.     AUTO    UBYTE                IOBuffer[HISCORESIZE];
  85.     AUTO    SWORD                mousex, mousey;
  86.     AUTO    UWORD                code, qual;
  87.     AUTO    ULONG                class, i;
  88.     AUTO    struct IntuiMessage* MsgPtr;
  89.     AUTO    struct MenuItem*     ItemPtr;
  90.     PERSIST ABOOL                clipboarded = FALSE;
  91.     PERSIST UBYTE                clipboard[FIELDX + 1][FIELDY + 1];
  92.  
  93.     say("Field Editor", WHITE);
  94.     setpointer(brush);
  95.     if (level > levels)
  96.         level = levels;
  97.     OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  98.     if (!clipboarded)
  99.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  100.  
  101.     /* draw pseudo-gadgets */
  102.     
  103.     clearscreen();
  104.     for (which = 0; which <= 6; which++)
  105.         DrawBevelBox(MainWindowPtr->RPort, STARTXPIXEL - 5 - (SQUAREX * 3), UNDERLINEOFFSET + (which * SQUAREY * 3), SQUAREX + 9, SQUAREY + 4, GT_VisualInfo, VisualInfoPtr);
  106.     SetAPen(MainWindowPtr->RPort, WHITE);
  107.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   EMPTYGADGET * SQUAREY));
  108.     Text(MainWindowPtr->RPort, "F1:", 3);
  109.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (  SILVERGADGET * SQUAREY));
  110.     Text(MainWindowPtr->RPort, "F2:", 3);
  111.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (    GOLDGADGET * SQUAREY));
  112.     Text(MainWindowPtr->RPort, "F3:", 3);
  113.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (DYNAMITEGADGET * SQUAREY));
  114.     Text(MainWindowPtr->RPort, "F4:", 3);
  115.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (    WOODGADGET * SQUAREY));
  116.     Text(MainWindowPtr->RPort, "F5:", 3);
  117.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   STONEGADGET * SQUAREY));
  118.     Text(MainWindowPtr->RPort, "F6:", 3);
  119.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   METALGADGET * SQUAREY));
  120.     Text(MainWindowPtr->RPort, "F7:", 3);
  121.  
  122.     draw(GADGETX,    EMPTYGADGET,    EMPTY);
  123.     draw(GADGETX,   SILVERGADGET,   SILVER);
  124.     draw(GADGETX,     GOLDGADGET,     GOLD);
  125.     draw(GADGETX, DYNAMITEGADGET, DYNAMITE);
  126.     draw(GADGETX,     WOODGADGET,     WOOD);
  127.     draw(GADGETX,    STONEGADGET,    STONE);
  128.     draw(GADGETX,    METALGADGET,    METAL);
  129.  
  130.     SetAPen(MainWindowPtr->RPort, BLACK);
  131.     RectFill
  132.     (   MainWindowPtr->RPort,
  133.         STARTXPIXEL - SQUAREX - 1,
  134.         UNDERLINEOFFSET - 1,
  135.         STARTXPIXEL - SQUAREX + 3,
  136.         UNDERLINEOFFSET + 4 + (SQUAREY * 19)
  137.     );
  138.     underline(brush);
  139.     
  140.     turborender();
  141.     saylevel(WHITE);
  142.     clearkybd();
  143.  
  144.     fex = startx[level];
  145.     fey = starty[level];
  146.     dot();
  147.  
  148.     if (!(ModifyIDCMP(MainWindowPtr, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | IDCMP_REFRESHWINDOW | IDCMP_MOUSEMOVE)))
  149.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  150.     cleanexit(EXIT_FAILURE);
  151.     }
  152.     while (a == FIELDEDIT)
  153.     {   while (MsgPtr = GT_GetIMsg(MainWindowPtr->UserPort))
  154.         {   class  = MsgPtr->Class;
  155.             code   = MsgPtr->Code;
  156.             qual   = MsgPtr->Qualifier;
  157.             mousex = MsgPtr->MouseX;
  158.             mousey = MsgPtr->MouseY;
  159.             if (class == IDCMP_MENUVERIFY)
  160.             {   if
  161.                 (   mousex >= STARTXPIXEL
  162.                  && mousex <=   ENDXPIXEL
  163.                  && mousey >= STARTYPIXEL
  164.                  && mousey <=   ENDYPIXEL
  165.                 )
  166.                 {   MsgPtr->Code = MENUCANCEL;
  167.             }   }
  168.             GT_ReplyIMsg(MsgPtr);
  169.             switch (class)
  170.             {
  171.             case IDCMP_MOUSEMOVE:
  172.                 if (leftdown)
  173.                 {   pointerx = xpixeltosquare(mousex);
  174.                     pointery = ypixeltosquare(mousey);
  175.                     if
  176.                     (   (pointerx != fex || pointery != fey)
  177.                      && valid(pointerx, pointery)
  178.                     )
  179.                     {   undot();
  180.                         fex = pointerx;
  181.                         fey = pointery;
  182.                         stamp(brush);
  183.                 }   }
  184.             break;
  185.             case IDCMP_MENUPICK:
  186.                 while (code != MENUNULL)
  187.                 {   ItemPtr = ItemAddress(MenuPtr, code);
  188.                     switch (MENUNUM(code))
  189.                     {
  190.                     case MN_PROJECT:
  191.                         switch (ITEMNUM(code))
  192.                         {
  193.                         case IN_NEW:
  194.                             effect(FXFILENEW);
  195.                             newfields();
  196.                             say("New done.", WHITE);
  197.                         break;
  198.                         case IN_OPEN:
  199.                             effect(FXFILEOPEN);
  200.                             fileopen(FALSE);
  201.                         break;
  202.                         case IN_REVERT:
  203.                             fileopen(TRUE);
  204.                         break;
  205.                         case IN_SAVE:
  206.                             effect(FXFILESAVE);
  207.                             if (modified)
  208.                             {   clearhiscores();
  209.                                 modified = FALSE;
  210.                             }
  211.                             filesaveas(FALSE);
  212.                             turborender();
  213.                         break;
  214.                         case IN_SAVEAS:
  215.                             effect(FXFILESAVEAS);
  216.                             if (modified)
  217.                             {   clearhiscores();
  218.                                 modified = FALSE;
  219.                             }
  220.                             filesaveas(TRUE);
  221.                             turborender();
  222.                         break;
  223.                         case IN_PROJECTDELETE:
  224.                             effect(FXEDITDELETE);
  225.                             filedelete();
  226.                         break;
  227.                         case IN_QUIT:
  228.                             if (verify())
  229.                                 cleanexit(EXIT_SUCCESS);
  230.                         break;
  231.                         default:
  232.                         break;
  233.                         }
  234.                     break;
  235.                     case MN_EDIT:
  236.                         switch (ITEMNUM(code))
  237.                         {
  238.                         case IN_CUT:
  239.                             effect(FXEDITCUT);
  240.                             for (x = 0; x <= FIELDX; x++)
  241.                                 for (y = 0; y <= FIELDY; y++)
  242.                                     clipboard[x][y] = board[level][x][y];
  243.                             leveldelete();
  244.                             clipboarded = TRUE;
  245.                             modified = TRUE;
  246.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  247.                         break;
  248.                         case IN_COPY:
  249.                             effect(FXEDITCOPY);
  250.                             for (x = 0; x <= FIELDX; x++)
  251.                                 for (y = 0; y <= FIELDY; y++)
  252.                                     clipboard[x][y] = board[level][x][y];
  253.                             clipboarded = TRUE;
  254.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  255.                         break;
  256.                         case IN_PASTE:
  257.                             effect(FXEDITPASTE);
  258.                             for (x = 0; x <= FIELDX; x++)
  259.                                 for (y = 0; y <= FIELDY; y++)
  260.                                     board[level][x][y] = clipboard[x][y];
  261.                             turborender();
  262.                             modified = TRUE;
  263.                         break;
  264.                         case IN_ERASE:
  265.                             levelerase();
  266.                         break;
  267.                         case IN_INSERT:
  268.                             levelinsert();
  269.                         break;
  270.                         case IN_EDITDELETE:
  271.                             effect(FXEDITDELETE);
  272.                             leveldelete();
  273.                         break;
  274.                         case IN_APPEND:
  275.                             levelappend();
  276.                         break;
  277.                         default:
  278.                         break;
  279.                         }
  280.                     break;
  281.                     case MN_SETTINGS:
  282.                         switch(ITEMNUM(code))
  283.                         {
  284.                         case IN_CREATEICONS:
  285.                             if (ItemPtr->Flags & CHECKED)
  286.                                 icons = TRUE;
  287.                             else icons = FALSE;
  288.                         break;
  289.                         default:
  290.                         break;
  291.                         }
  292.                     break;
  293.                     case MN_HELP:
  294.                         switch(ITEMNUM(code))
  295.                         {
  296.                         case IN_CREATURES:
  297.                             help(ORB);
  298.                         break;
  299.                         case IN_OBJECTS:
  300.                             help(AFFIXER);
  301.                         break;
  302.                         case IN_MANUAL:
  303.                             helpmanual();
  304.                         break;
  305.                         case IN_ABOUT:
  306.                             helpabout();
  307.                         break;
  308.                         default:
  309.                         break;
  310.                         }
  311.                     break;
  312.                     default:
  313.                     break;
  314.                     } // hctiws
  315.                     code = ItemPtr->NextSelect;
  316.                 } // elihw
  317.             break;
  318.             case IDCMP_RAWKEY:
  319.                 if (!(qual & IEQUALIFIER_REPEAT))
  320.                 {   effect(FXCLICK);
  321.                 }
  322.                 switch(code)
  323.                 {
  324.                 case DELETE:
  325.                     if (!(qual & IEQUALIFIER_REPEAT))
  326.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  327.                             level = 1;
  328.                         elif (--level < 0)
  329.                             level = levels;
  330.                         saylevel(WHITE);
  331.                         turborender();
  332.                     }
  333.                 break;
  334.                 case HELP:
  335.                     if (!(qual & IEQUALIFIER_REPEAT))
  336.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  337.                             level = levels;
  338.                         elif (++level > levels)
  339.                             level = 0;
  340.                         saylevel(WHITE);
  341.                         turborender();
  342.                     }
  343.                 break;
  344.                 case Z:
  345.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  346.                     {   /* The undocumented merge function. You will
  347.                         notice that there is absolutely no error checking.
  348.                         This is because you shouldn't really be using this
  349.                         function, unless you know what you are doing. */
  350.  
  351.                         say("Merging...", WHITE);
  352.                         ZOpen("RAM:Merge.fset", FALSE);
  353.                         ZRead(IOBuffer, 10);
  354.                         mergelevels = IOBuffer[9];
  355.                         for (i = 0; i <= HISCORES; i++)
  356.                         {   ZRead(IOBuffer, HISCORESIZE);
  357.                         }
  358.                         ZRead(IOBuffer, 8);
  359.                         ZRead((char *) &board[0][0][0], LEVELSIZE);
  360.  
  361.                         for (i = levels + 1; i <= levels + mergelevels; i++)
  362.                         {   ZRead(IOBuffer, 8);
  363.                             startx[i]            = IOBuffer[0];
  364.                             starty[i]            = IOBuffer[1];
  365.                             teleport[i][0].alive = IOBuffer[2];
  366.                             teleport[i][0].x     = IOBuffer[3];
  367.                             teleport[i][0].y     = IOBuffer[4];
  368.                             teleport[i][1].alive = IOBuffer[5];
  369.                             teleport[i][1].x     = IOBuffer[6];
  370.                             teleport[i][1].y     = IOBuffer[7];
  371.                             ZRead((char *) &board[i][0][0], LEVELSIZE);
  372.                         }
  373.                         ZClose();
  374.                         levels += mergelevels;
  375.                         modified = clearthem = TRUE;
  376.                         say("Merge done.", WHITE);
  377.                     }
  378.                 break;
  379.                 case M:
  380.                     if (!(qual & IEQUALIFIER_REPEAT))
  381.                         toggle(M);
  382.                 break;
  383.                 case F:
  384.                     if (!(qual & IEQUALIFIER_REPEAT))
  385.                         toggle(F);
  386.                 break;
  387.                 case ESCAPE:
  388.                     if (!(qual & IEQUALIFIER_REPEAT))
  389.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  390.                         {   if (verify())
  391.                             {   cleanexit(EXIT_SUCCESS);
  392.                         }   }
  393.                         else
  394.                         {   a = GAMEOVER;
  395.                     }   }
  396.                 break;
  397.                 case SPACEBAR:
  398.                 case RETURN:
  399.                 case ENTER:
  400.                     if (!(qual & IEQUALIFIER_REPEAT))
  401.                         a = GAMEOVER;
  402.                 break;
  403.                 case NUMERICOPEN:
  404.                     setpointer(NORMAL);
  405.                     underline(255);
  406.  
  407.                     brush--;
  408.                     if (brush <= 0 || brush > LASTOBJECT) // note sign issues
  409.                     {   brush = LASTOBJECT;
  410.                     }   stamp(brush);
  411.                 break;
  412.                 case NUMERICCLOSE:
  413.                     setpointer(NORMAL);
  414.                     underline(255);
  415.  
  416.                     brush++;
  417.                     if (brush > LASTOBJECT)
  418.                     {   brush = 0;
  419.                         stamp(brush);
  420.                     }
  421.                 break;
  422.                 case C:
  423.                     effect(FXCENTRE); /* interesting */
  424.                     undot();
  425.                     fex = FIELDX / 2;
  426.                     fey = FIELDY / 2;
  427.                     dot();
  428.                 break;
  429.                 case S:
  430.                     stamp(START);
  431.                 break;
  432.                 case KEY_T:
  433.                     stamp(TELEPORT);
  434.                 break;
  435.                 case O:
  436.                     stamp(OCTOPUS);
  437.                 break;
  438.                 case ALPHAONE:
  439.                     stamp(EMPTY);
  440.                 break;
  441.                 case ALPHATWO:
  442.                     stamp(SILVER);
  443.                 break;
  444.                 case ALPHATHREE:
  445.                     stamp(GOLD);
  446.                 break;
  447.                 case ALPHAFOUR:
  448.                     stamp(DYNAMITE);
  449.                 break;
  450.                 case ALPHAFIVE:
  451.                     stamp(WOOD);
  452.                 break;
  453.                 case ALPHASIX:
  454.                     stamp(STONE);
  455.                 break;
  456.                 case ALPHASEVEN:
  457.                     stamp(METAL);
  458.                 break;
  459.                 case F1:
  460.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  461.                     {   fillfield(EMPTY);
  462.                     } else setbrush(EMPTY);
  463.                 break;
  464.                 case F2:
  465.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  466.                     {   fillfield(SILVER);
  467.                     } else setbrush(SILVER);
  468.                 break;
  469.                 case F3:
  470.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  471.                     {   fillfield(GOLD);
  472.                     } else setbrush(GOLD);
  473.                 break;
  474.                 case F4:
  475.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  476.                     {   fillfield(DYNAMITE);
  477.                     } else setbrush(DYNAMITE);
  478.                 break;
  479.                 case F5:
  480.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  481.                     {   fillfield(WOOD);
  482.                     } else setbrush(WOOD);
  483.                 break;
  484.                 case F6:
  485.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  486.                     {   fillfield(STONE);
  487.                     } else setbrush(STONE);
  488.                 break;
  489.                 case F7:
  490.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  491.                     {   fillfield(METAL);
  492.                     } else setbrush(METAL);
  493.                 break;
  494.                 case NUMERICZERO:
  495.                     if (!(qual & IEQUALIFIER_REPEAT))
  496.                     {   if (!sticky)
  497.                         {   sticky = TRUE;
  498.                             say("Sticky mode on", WHITE);
  499.                             stamp(brush);
  500.                         } else
  501.                         {   sticky = FALSE;
  502.                             say("Sticky mode off", WHITE);
  503.                             dot();
  504.                     }   }
  505.                 break;
  506.                 case NUMERICDOT:
  507.                     stamp(brush);
  508.                 break;
  509.                 case KEY_X:
  510.                     undot();
  511.                     fex = FIELDX - fex;
  512.                     dot();
  513.                 break;
  514.                 case KEY_Y:
  515.                     undot();
  516.                     fey = FIELDY - fey;
  517.                     dot();
  518.                 break;
  519.                 case NUMERICFOUR:
  520.                 case LEFT:
  521.                     undot();
  522.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  523.                     {   fex = 0;
  524.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  525.                     {   fex = xwrap(fex - ALTJUMP);
  526.                     } else
  527.                     {   fex = xwrap(fex - 1);
  528.                     }
  529.                     if (sticky)
  530.                     {   stamp(brush);
  531.                     } else
  532.                     {   dot();
  533.                     }
  534.                 break;
  535.                 case NUMERICSIX:
  536.                 case RIGHT:
  537.                     undot();
  538.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  539.                     {   fex = FIELDX;
  540.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  541.                     {   fex = xwrap(fex + ALTJUMP);
  542.                     } else
  543.                     {   fex = xwrap(fex + 1);
  544.                     }
  545.                     if (sticky)
  546.                     {   stamp(brush);
  547.                     } else
  548.                     {   dot();
  549.                     }
  550.                 break;
  551.                 case NUMERICEIGHT:
  552.                 case UP:
  553.                     undot();
  554.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  555.                     {   fey = 0;
  556.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  557.                     {   fey = ywrap(fey - ALTJUMP);
  558.                     } else
  559.                     {   fey = ywrap(fey - 1);
  560.                     }
  561.                     if (sticky)
  562.                     {   stamp(brush);
  563.                     } else
  564.                     {   dot();
  565.                     }
  566.                 break;
  567.                 case NUMERICFIVE:
  568.                 case NUMERICTWO:
  569.                 case DOWN:
  570.                     undot();
  571.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  572.                     {   fey = FIELDY;
  573.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  574.                     {   fey = ywrap(fey + ALTJUMP);
  575.                     } else
  576.                     {   fey = ywrap(fey + 1);
  577.                     }
  578.                     if (sticky)
  579.                     {   stamp(brush);
  580.                     } else
  581.                     {   dot();
  582.                     }
  583.                 break;
  584.                 case NUMERICSEVEN:
  585.                     undot();
  586.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  587.                     {   fex = 0;
  588.                         fey = 0;
  589.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  590.                     {   fex = xwrap(fex - ALTJUMP);
  591.                         fey = ywrap(fey - ALTJUMP);
  592.                     } else
  593.                     {   fex = xwrap(fex - 1);
  594.                         fey = ywrap(fey - 1);
  595.                     }
  596.                     if (sticky)
  597.                     {   stamp(brush);
  598.                     } else
  599.                     {   dot();
  600.                     }
  601.                 break;
  602.                 case NUMERICNINE:
  603.                     undot();
  604.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  605.                     {   fex = FIELDX;
  606.                         fey = 0;
  607.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  608.                     {   fex = xwrap(fex + ALTJUMP);
  609.                         fey = ywrap(fey - ALTJUMP);
  610.                     } else
  611.                     {   fex = xwrap(fex + 1);
  612.                         fey = ywrap(fey - 1);
  613.                     }
  614.                     if (sticky)
  615.                     {   stamp(brush);
  616.                     } else
  617.                     {   dot();
  618.                     }
  619.                 break;
  620.                 case NUMERICONE:
  621.                     undot();
  622.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  623.                     {   fex = 0;
  624.                         fey = FIELDY;
  625.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  626.                     {   fex = xwrap(fex - ALTJUMP);
  627.                         fey = ywrap(fey + ALTJUMP);
  628.                     } else
  629.                     {   fex = xwrap(fex - 1);
  630.                         fey = ywrap(fey + 1);
  631.                     }
  632.                     if (sticky)
  633.                     {   stamp(brush);
  634.                     } else
  635.                     {   dot();
  636.                     }
  637.                 break;
  638.                 case NUMERICTHREE:
  639.                     undot();
  640.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  641.                     {   fex = FIELDX;
  642.                         fey = FIELDY;
  643.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  644.                     {   fex = xwrap(fex + ALTJUMP);
  645.                         fey = ywrap(fey + ALTJUMP);
  646.                     } else
  647.                     {   fex = xwrap(fex + 1);
  648.                         fey = ywrap(fey + 1);
  649.                     }
  650.                     if (sticky)
  651.                     {   stamp(brush);
  652.                     } else
  653.                     {   dot();
  654.                     }
  655.                 break;
  656.                 default:
  657.                 break;
  658.                 } // hctiws
  659.             break;
  660.             case IDCMP_MOUSEBUTTONS:
  661.                 if (code == SELECTDOWN)
  662.                 {   pointerx = xpixeltosquare(mousex);
  663.                     pointery = ypixeltosquare(mousey);
  664.                     leftdown = TRUE;
  665.                     if (pointerx == GADGETX)
  666.                     {   switch (pointery)
  667.                         {
  668.                         case GOLDGADGET:
  669.                             setbrush(GOLD);
  670.                         break;
  671.                         case SILVERGADGET:
  672.                             setbrush(SILVER);
  673.                         break;
  674.                         case EMPTYGADGET:
  675.                             setbrush(EMPTY);
  676.                         break;
  677.                         case WOODGADGET:
  678.                             setbrush(WOOD);
  679.                         break;
  680.                         case DYNAMITEGADGET:
  681.                             setbrush(DYNAMITE);
  682.                         break;
  683.                         case STONEGADGET:
  684.                             setbrush(STONE);
  685.                         break;
  686.                         case METALGADGET:
  687.                             setbrush(METAL);
  688.                         break;
  689.                         default:
  690.                         break;
  691.                     }   }
  692.                     else
  693.                     {   if (valid(pointerx, pointery))
  694.                         {   undot();
  695.                             fex = pointerx;
  696.                             fey = pointery;
  697.                             stamp(brush);
  698.                 }   }   }
  699.                 elif (code == SELECTUP)
  700.                 {   leftdown = FALSE;
  701.                 } elif (code == MENUUP)
  702.                 {   pointerx = xpixeltosquare(mousex);
  703.                     pointery = ypixeltosquare(mousey);
  704.                     if (valid(pointerx, pointery))
  705.                     {   undot();
  706.                         fex = pointerx;
  707.                         fey = pointery;
  708.                         stamp(EMPTY);
  709.                 }   }
  710.             break;
  711.             case IDCMP_CLOSEWINDOW:
  712.                 cleanexit(EXIT_SUCCESS);
  713.             break;
  714.             case IDCMP_REFRESHWINDOW:
  715.                 GT_BeginRefresh(MainWindowPtr);
  716.                 GT_EndRefresh(MainWindowPtr, TRUE);
  717.             break;
  718.             default:
  719.                 /* IDCMP_MENUVERIFY, IDCMP_INTUITICKS, IDCMP_ACTIVEWINDOW */
  720.             break;
  721.     }   }   }
  722.  
  723.     /* exit to title screen */
  724.  
  725.     if (!(ModifyIDCMP(MainWindowPtr->RPort, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS)))
  726.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  727.     cleanexit(EXIT_FAILURE);
  728.     }
  729.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  730.     if (timer)
  731.     {   AbortIO((struct IORequest *) TimerRqPtr);
  732.          WaitIO((struct IORequest *) TimerRqPtr);
  733.     }
  734.     setpointer(NORMAL);
  735.     if (clearthem)
  736.         clearhiscores();
  737.     matchteleports();
  738. }
  739.  
  740. MODULE void stamp(UBYTE square)
  741. {   if (square == START)
  742.     {   draw(startx[level], starty[level], EMPTY);
  743.         board[level][startx[level]][starty[level]] = EMPTY;
  744.         startx[level] = fex;
  745.         starty[level] = fey;
  746.         board[level][fex][fey] = EMPTY;
  747.     } else
  748.     {   board[level][fex][fey] = square;
  749.     }
  750.  
  751.     draw(fex, fey, square);
  752.     dot();
  753.     modified = clearthem = TRUE;
  754. }
  755.  
  756. MODULE void undot(void)
  757. {   if (startx[level] == fex && starty[level] == fey)
  758.         draw(fex, fey, START);
  759.     else draw(fex, fey, board[level][fex][fey]);
  760. }
  761.  
  762. MODULE void fillfield(UBYTE which)
  763. {   SBYTE x, y;
  764.  
  765.     // Service routine for field editor.
  766.  
  767.     for (x = 0; x <= FIELDX; x++)
  768.     {   for (y = 0; y <= FIELDY; y++)
  769.         {   board[level][x][y] = which;
  770.             draw(x, y, which);
  771.     }   }
  772.     board[level][startx[level]][starty[level]] = EMPTY;
  773.     draw(startx[level], starty[level], START);
  774.     dot();
  775. }
  776.  
  777. AGLOBAL void setbrush(UBYTE newbrush)
  778. {   brush = newbrush;
  779.     setpointer(brush);
  780.     underline(brush);
  781. }
  782.  
  783. MODULE void underline(UBYTE square)
  784. {   /* Removes old underline, draws new underline.
  785.  
  786.     square: which square-type to underline, or 255 for clear only.
  787.     Squares which do not correspond to any pseudo-gadgets
  788.     (eg. objects) are converted to 255s. */
  789.  
  790.     PERSIST SWORD oldy = 255;
  791.     AUTO    SWORD y;
  792.  
  793.     switch(square)
  794.     {
  795.     case EMPTY:
  796.         y = UNDERLINEOFFSET;
  797.     break;
  798.     case SILVER:
  799.         y = UNDERLINEOFFSET + (SQUAREY *  3);
  800.     break;
  801.     case GOLD:
  802.         y = UNDERLINEOFFSET + (SQUAREY *  6);
  803.     break;
  804.     case DYNAMITE:
  805.         y = UNDERLINEOFFSET + (SQUAREY *  9);
  806.     break;
  807.     case WOOD:
  808.         y = UNDERLINEOFFSET + (SQUAREY * 12);
  809.     break;
  810.     case STONE:
  811.         y = UNDERLINEOFFSET + (SQUAREY * 15);
  812.     break;
  813.     case METAL:
  814.         y = UNDERLINEOFFSET + (SQUAREY * 18);
  815.     break;
  816.     default:
  817.         square = 255;
  818.         y = 0; // to avoid spurious warnings
  819.     break;
  820.     }
  821.  
  822.     if (oldy != 255)
  823.     {   SetAPen(MainWindowPtr->RPort, BLACK);
  824.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy);
  825.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy + SQUAREY + 3);
  826.     }
  827.     if (square != 255)
  828.     {   SetAPen(MainWindowPtr->RPort, WHITE);
  829.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y);
  830.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y + SQUAREY + 3);
  831.         oldy = y;
  832. }   }
  833.  
  834. MODULE void dot(void)
  835. {    SWORD xx, yy;
  836.  
  837.     /* Squares are dotted as follows:
  838.     
  839.      012345678
  840.     0.........
  841.     1.........
  842.     2...WWW...
  843.     3...WWWB..
  844.     4....BBB..
  845.     5......... */
  846.  
  847.     xx = (fex * SQUAREX) + STARTXPIXEL;
  848.     yy = (fey * SQUAREY) + STARTYPIXEL;
  849.  
  850.     if (sticky)
  851.         SetAPen(MainWindowPtr->RPort, RED);
  852.     else SetAPen(MainWindowPtr->RPort, WHITE);
  853.     WritePixel(MainWindowPtr->RPort, xx + 3, yy + 2);
  854.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 2);
  855.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 2);
  856.     WritePixel(MainWindowPtr->RPort, xx + 3, yy + 3);
  857.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 3);
  858.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 3);
  859.     SetAPen(MainWindowPtr->RPort, BLACK);
  860.     WritePixel(MainWindowPtr->RPort, xx + 6, yy + 3);
  861.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 4);
  862.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 4);
  863.     WritePixel(MainWindowPtr->RPort, xx + 6, yy + 4);
  864. }
  865.  
  866. MODULE void setpointer(UBYTE pointer) {
  867. switch (pointer) {
  868. case GOLD:
  869.         SetRGB4(&ScreenPtr->ViewPort, 17, 10, 10,  2);          /* fill */
  870.     SetRGB4(&ScreenPtr->ViewPort, 18,  8,  4,  2);        /* shadow */
  871.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12,  2);        /* shine */
  872.         SetPointer(MainWindowPtr, CustomPointer, 6, 5, -3, -2);
  873.     break;
  874. case SILVER:
  875.         SetRGB4(&ScreenPtr->ViewPort, 17, 11, 11, 11);          /* fill */
  876.     SetRGB4(&ScreenPtr->ViewPort, 18,  6,  6,  6);        /* shadow */
  877.     SetRGB4(&ScreenPtr->ViewPort, 19, 15, 15, 15);        /* shine */
  878.         SetPointer(MainWindowPtr, CustomPointer, 6, 5, -3, -2);
  879.     break;
  880. case EMPTY:
  881.         SetRGB4(&ScreenPtr->ViewPort, 17,  5,  5,  5);          /* fill */
  882.     SetRGB4(&ScreenPtr->ViewPort, 18,  0,  0,  0);        /* shadow */
  883.         SetRGB4(&ScreenPtr->ViewPort, 19,  9,  9,  9);          /* shine */
  884.         SetPointer(MainWindowPtr, CustomPointer, 6, 5, -3, -2);
  885.     break;
  886. case WOOD:
  887.     SetRGB4(&ScreenPtr->ViewPort, 17,  8,  4,  2);        /* fill */
  888.         SetRGB4(&ScreenPtr->ViewPort, 18,  5,  5,  5);          /* shadow */
  889.         SetRGB4(&ScreenPtr->ViewPort, 19, 10, 10,  2);          /* shine */
  890.         SetPointer(MainWindowPtr, CustomPointer, 6, 5, -3, -2);
  891.     break;
  892. case STONE:
  893.     SetRGB4(&ScreenPtr->ViewPort, 17,  0,  0,  0);        /* fill */
  894.         SetRGB4(&ScreenPtr->ViewPort, 18,  5,  5,  5);          /* shadow */
  895.         SetRGB4(&ScreenPtr->ViewPort, 19,  9,  9,  9);          /* shine */
  896.         SetPointer(MainWindowPtr, CustomPointer, 6, 5, -3, -2);
  897.     break;
  898. case METAL:
  899.     SetRGB4(&ScreenPtr->ViewPort, 17,  6,  6, 15);        /* fill */
  900.     SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3, 15);        /* shadow */
  901.         SetRGB4(&ScreenPtr->ViewPort, 19, 11, 11, 11);          /* shine */
  902.         SetPointer(MainWindowPtr, CustomPointer, 6, 5, -3, -2);
  903.     break;
  904. default:
  905.     SetRGB4(&ScreenPtr->ViewPort, 17, 14,  4,  4);        /* fill */
  906.     SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3,  3);        /* shadow */
  907.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 12);        /* shine */
  908.     ClearPointer(MainWindowPtr);
  909.     break;
  910. }   }
  911.  
  912. MODULE SBYTE xpixeltosquare(SWORD x)
  913. {   x = (x - STARTXPIXEL) / SQUAREX;
  914.     if (x < 0)
  915.         x--;
  916.     return ((SBYTE) x);
  917. }
  918. MODULE SBYTE ypixeltosquare(SWORD y)
  919. {   y = (y - STARTYPIXEL) / SQUAREY;
  920.     if (y < 0)
  921.         y--;
  922.     return ((SBYTE) y);
  923. }
  924.  
  925. MODULE void levelappend(void)
  926. {   UBYTE oldlevel;
  927.  
  928.     if (levels < MAXLEVELS)
  929.     {   oldlevel = level;
  930.         level = ++levels;
  931.         newfield();
  932.         level = oldlevel;
  933.         saylevel(WHITE);
  934. }   }
  935. MODULE void leveldelete(void)
  936. {   SBYTE i;
  937.  
  938.     /* pull boards */
  939.  
  940.     if (levels > 1)
  941.     {   if (level < levels)
  942.         for (i = level; i < levels; i++)
  943.             copyfield(i + 1, i);
  944.         else
  945.             level--;
  946.         levels--;
  947.         saylevel(WHITE);
  948.         turborender();
  949. }   }
  950. MODULE void levelerase(void)
  951. {   newfield();
  952.     turborender();
  953. }
  954. MODULE void levelinsert(void)
  955. {   UBYTE i;
  956.  
  957.     /* push boards */
  958.  
  959.     if (levels < MAXLEVELS)
  960.     {   for (i = levels; i >= level; i--)
  961.             copyfield(i, i + 1);
  962.         levels++;
  963.         saylevel(WHITE);
  964.         newfield();
  965.         turborender();
  966. }   }
  967. MODULE void copyfield(UBYTE source, UBYTE destination)
  968. {   SBYTE which, x, y;
  969.  
  970.     for (x = 0; x <= FIELDX; x++)
  971.         for (y = 0; y <= FIELDY; y++)
  972.             board[destination][x][y] = board[source][x][y];
  973.     startx[destination] = startx[source];
  974.     starty[destination] = starty[source];
  975.     for (which = 0; which <= 1; which++)
  976.     {   teleport[destination][which].alive = teleport[source][which].alive;
  977.         teleport[destination][which].x     = teleport[source][which].x;
  978.         teleport[destination][which].y     = teleport[source][which].y;
  979. }   }
  980.